﻿using System;
using System.Collections.Generic;
using System.Linq;
using Sustainalytics.Reporting.Framework;
using Foxit.PDF.PageElements;
using Foxit.PDF;
using Sustainalytics.RiskRatings.Reporting.Charts;
using Sustainalytics.Entities.RiskRatings;
using Foxit.PDF.Imaging;
using Sustainalytics.Entities;
using Sustainalytics.Utils;

namespace Sustainalytics.RiskRatings.Reporting
{
    public class CorporateGovernanceSection : PdfReportSectionGenerator
    {
        private static readonly IndicatorCodeComparer _indicatorComparer = new IndicatorCodeComparer();

        public CorporateGovernanceSection(int index) : base(index)
        {
            this._reportSection.Name = "Corporate Governance Section";
        }

        public override void ComposeSectionContent()
        {
            if (_dataSource.CompanyProfile.MaterialEsgIssues.Any())
            {
                var issue = _dataSource.CompanyProfile.MaterialEsgIssues
                    .FirstOrDefault(x => x.Type == MaterialIssueType.BaselineIssue);


                var page = new PdfReportPage_MaterialIssues(_report, _dataSource, issue, ReportHelper.GetMeiImage(issue.ExternalId.ToString(), MeiImageColor.Colored, MeiImageSize.Large));
                _report.Pages.Add(page);
                float currentYOffset = page.Top;

                AddFirstPage(issue, page, 0, currentYOffset, _report.PageMaxWidth);

                //List<GovernancePillars> pillarsList = new List<GovernancePillars>();
                //if (_dataSource.GovernancePillarsList.Any())
                //{
                //    pillarsList = _dataSource.GovernancePillarsList;
                //}
                //else
                //{
                //    if (_dataSource.CompanyProfile.MaterialEsgIssues.First(x => x.Type == MaterialIssueType.BaselineIssue).Indicators.Count() == 1)
                //    {
                //        var indicator = _dataSource.CompanyProfile.MaterialEsgIssues.First(x => x.Type == MaterialIssueType.BaselineIssue).Indicators.ToList()[0];
                //    }
                //}

                page = new PdfReportPage_MaterialIssues(_report, _dataSource, issue, ReportHelper.GetMeiImage(issue.ExternalId.ToString(), MeiImageColor.Colored, MeiImageSize.Large));
                _report.Pages.Add(page);

                AddSecondPage(issue, page, 0, currentYOffset, _report.PageMaxWidth);
            }
        }

        private void AddFirstPage(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            var columnWidth = (maxWidth - (float)HorisontalSpacing.Large) / 2;
            float currentYOffset = y;

            OutlinePositions.Add(new OutlinePosition { Name = issue.Name, PageNumber = OutlinePageCount, VerticalPosition = page.Top - HeaderHeight });
            page.Elements.Add(new Line(x, y - 10f, x + maxWidth, y - 10f, 1, Colors.LineColor));

            currentYOffset = AddIssueEsgRiskRating(issue, page, x, currentYOffset, columnWidth);

            currentYOffset = AddIssueRiskAnalysisSection(issue,page, x, currentYOffset, columnWidth);

            

            AddMeiRiskDetailsChart(issue, page, 0, currentYOffset, _report.PageMaxWidth);
        }

        private void AddSecondPage(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            var management_details_image = ReportHelper.GetFile("icon-management.png");
            page.Elements.Add(new Image(ImageData.GetImage(management_details_image), 0, y , 0.3f));
            page.Elements.Add(new Label("Corporate Governance Pillars", 35, y + 10f, 150f, 12f, Fonts.MontserratBold, 10f, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Line(190, y + 17f, _report.PageMaxWidth, y + 15f, 1, RgbColor.Black));
            var currentYOffset = AddPillarsTable(issue, page, x, y+35f, maxWidth, page.Dimensions.Height);
            if (!_dataSource.GovernancePillarsList.Any())
            {
                //Company is private, put a message
                currentYOffset += 50;
                page.Elements.Add(new Image(ImageData.GetImage(management_details_image), 40, currentYOffset, 0.4f));
                var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus semper, lorem eu ullamcorper lacinia, sapien velit tincidunt dui, vel finibus justo risus ullamcorper ligula.";
                page.Elements.Add(new TextArea(text, 100, currentYOffset+10, 350,200, Fonts.RobotoRegular,8,TextAlign.Left, RgbColor.Black));
            }
        }

        private float AddIssueRiskAnalysisSection(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            var currentYOffset = y;
            var width = page.Dimensions.Width;
            var issue_risk_details = ReportHelper.GetFile("icon-risk-analysis.png");
            page.Elements.Add(new Image(ImageData.GetImage(issue_risk_details), x, currentYOffset - 11f, 0.25f));
            page.Elements.Add(new Label("Risk Analysis", x + 30f, currentYOffset - 6f, 100f, 12f, Fonts.MontserratBold, 10f, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Line(x + 135, currentYOffset, _report.PageMaxWidth, currentYOffset, 1, RgbColor.Black));

            currentYOffset += 20;

            //Exposure Section
            page.Elements.Add(new Label("Exposure Score", x + 3f, currentYOffset, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            currentYOffset += 15;
            var exposureScore = issue.ManagementRisk.Exposure.Value.ToString("#0.0");
            var assesmentExposure = issue.ExposureCluster.ToString();
            double meiSubIndustryExp = 0;
            double meiSubIndustryManagement = 0;

            page.Elements.Add(new Label(exposureScore, x + 3f, currentYOffset +10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Label(" /20+", x + 18f, currentYOffset + 10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Gray));
            page.Elements.Add(new Label(assesmentExposure, x + 40f, currentYOffset + 10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));

            RiskRating_RiskAnalysisRangeChart chartObjExposure = new RiskRating_RiskAnalysisRangeChart();
            chartObjExposure.Top = currentYOffset;
            chartObjExposure.Left = x + 80f;
            chartObjExposure.Width = 20f;
            chartObjExposure.ChartType= RiskChartType.MEI;
            chartObjExposure.Type = "Exposure";
            chartObjExposure.Value = (float)issue.ManagementRisk.Exposure.Value;
            chartObjExposure.Assessment = assesmentExposure;
            chartObjExposure.ExposureClusterList = _dataSource.ExposureClusters.Where(s=>s.Type== RiskRatingClusterType.MEI).ToList();
            page.Elements.Add(chartObjExposure);

            foreach (var meiBenchmark in _dataSource.Benchmark.MaterialEsgIssueBenchmarks)
            {
                if (meiBenchmark.MeiExternalId == issue.ExternalId)
                {

                    meiSubIndustryExp = meiBenchmark.SubIndustryPerformanceExposure.Average;
                    meiSubIndustryManagement = meiBenchmark.SubIndustryPerformanceManagement.Average;
                }

            }

            // Exposure/ Management Scatter Chart
            var columnWidth = width / 3 - 20f;
            var MeiManagement = issue.ManagementRisk.Management.Value;
            var MeiExposure = issue.ManagementRisk.Exposure.Value;
            var chart = new RiskRating_ScatterChart(x+200f, y + 20f, columnWidth)
            {
                SubPeerGroupBenchmark = _dataSource.Benchmark.MaterialEsgIssueBenchmarks.First(mei => mei.MeiExternalId == issue.ExternalId).PeersList,
                ShowGridLines = true,
                ChartType = ScatterChartType.Baseline,
                CompanyId = _dataSource.CompanyId,
                MeiExposure = MeiExposure,
                MeiManagament = MeiManagement,
                SubIndustry = _dataSource.CompanyProfile.SubPeerGroup,
                SubIndustryMEIAvgExposure=meiSubIndustryExp,
                SubIndustryMEIAvgManagement=meiSubIndustryManagement,
                SubIndustryDataPoints = _dataSource.SubIndustryMEIRiskRatingPerformanceDictionary.ContainsKey(issue.ExternalId) ? _dataSource.SubIndustryMEIRiskRatingPerformanceDictionary[issue.ExternalId] : new List<SubIndustryRiskRatingPerformance>(),
                GlobalUniverseDataPoints = _dataSource.GlobalUniverseMEIRiskRatingPerformanceDictionary.ContainsKey(issue.ExternalId) ? _dataSource.GlobalUniverseMEIRiskRatingPerformanceDictionary[issue.ExternalId] : new List<GlobalUniverseRiskRatingPerformance>(),
                RiskRatingClusterList = _dataSource.OverallClusters
            };
            page.Elements.Add(chart);

            //legend of the chart
            var left = x + 2 * columnWidth + 20f;
            var top = y + 5f;
            var circleSmallRadius = columnWidth / 75;
            var circleLargeRadius = circleSmallRadius * 2.5f;
            var globalUniversePointsColor = new RgbColor(204, 204, 204);
            var subIndustryPointsColor = new RgbColor(29, 96, 148);
            var legendXOffset = left + 30;
            var legendYOffset = top + 20;
            page.Elements.Add(new Circle(legendXOffset, legendYOffset, circleSmallRadius, circleSmallRadius, globalUniversePointsColor, globalUniversePointsColor, 1f, LineStyle.Solid));
            page.Elements.Add(new Label("Global Universe", legendXOffset + 5f, legendYOffset - 3, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));
            legendYOffset += 10;
            page.Elements.Add(new Circle(legendXOffset, legendYOffset, circleSmallRadius, circleSmallRadius, subIndustryPointsColor, subIndustryPointsColor, 1f, LineStyle.Solid));
            page.Elements.Add( new Label(_dataSource.CompanyProfile.SubPeerGroup + " (Subindustry)", legendXOffset + 5f, legendYOffset - 3, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));
            legendYOffset += 10;
            page.Elements.Add(new Circle(legendXOffset, legendYOffset, circleSmallRadius, circleSmallRadius, RgbColor.Black, RgbColor.Black, 1f, LineStyle.Solid));
            page.Elements.Add(new Label(_dataSource.CompanyProfile.CompanyName, legendXOffset + 5f, legendYOffset - 3, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));
            legendYOffset += 10;
            page.Elements.Add(
                 new Label("+", legendXOffset - 3f, legendYOffset - 3f, 150, (float)TextSizes.RegularText + 2, Fonts.RobotoRegular, (float)TextSizes.RegularText + 2, TextAlign.Left, RgbColor.Orange));
            page.Elements.Add(
              new Label("SubIndustryAvg.", legendXOffset + 5f, legendYOffset - 3f, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));

            currentYOffset += 50;

            //Management section
            page.Elements.Add(new Label("Management Score", x + 3f, currentYOffset, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            currentYOffset += 15;
            var managementScore = issue.ManagementRisk.Management.Value.ToString("#0.0");
            var assesmentManagement = issue.ManagementCluster.ToString();

            page.Elements.Add(new Label(managementScore, x + 3f, currentYOffset+10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Label(" /100", x + 18f, currentYOffset + 10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Gray));
            page.Elements.Add(new Label(assesmentManagement, x +40f, currentYOffset + 10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));


            RiskRating_RiskAnalysisRangeChart chartObjM = new RiskRating_RiskAnalysisRangeChart();
            chartObjM.Top = currentYOffset;
            chartObjM.Left = x + 80f;
            chartObjM.Width = 20f;
            chartObjM.Type = "Management";
            chartObjM.Value = (float)issue.ManagementRisk.Management.Value;
            chartObjM.Assessment = assesmentManagement;
            chartObjM.ManagementClusterList= _dataSource.ManagementClusters.Where(s => s.Type == RiskRatingClusterType.MEI).ToList();
            page.Elements.Add(chartObjM);

            currentYOffset += 110f;

            return currentYOffset;
        }

        private float AddPillarControl(GovernancePillars pillar, PdfReportPage page, float x, float y, float maxWidth)
        {
            var columnWidth = (maxWidth - (float)HorisontalSpacing.Large) / 2;
            float currentYOffset_Left = y;

            page.Elements.Add(new Label(pillar.Name, x, currentYOffset_Left, columnWidth * 4 / 5, 10, Fonts.RobotoBold, 10, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Image(ImageData.GetImage(ReportHelper.GetFile($"{pillar.Number.Replace(".", "_").ToUpperInvariant()}.png")), columnWidth * 4 / 5 + 15, currentYOffset_Left, 0.4f));
            currentYOffset_Left += 15;

            page.Elements.Add(new Label(pillar.Score.ToString("0"), x, currentYOffset_Left, 20, 13, Fonts.RobotoRegular, 16, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Label(pillar.Assessment.GetDisplayName(), x + 23, currentYOffset_Left + 3, 100, 10, Fonts.RobotoRegular, 10, TextAlign.Left, RgbColor.Black));
            currentYOffset_Left += 15;

            page.Elements.Add(new Label("Score", x, currentYOffset_Left + 2, 30, 6, Fonts.RobotoRegular, 6, TextAlign.Left, RgbColor.Black));
            currentYOffset_Left += 15;


            if (string.IsNullOrWhiteSpace(pillar.Comment))
            {
                var formattedTextArea = new FormattedTextArea(pillar.Comment, x, currentYOffset_Left, columnWidth, 300, Fonts.RobotoFontFamily, (int)TextSizes.RegularText, false);

                var requiredHeight = formattedTextArea.GetRequiredHeight();

                page.Elements.Add(new FormattedTextArea(pillar.Comment, x, currentYOffset_Left, columnWidth, requiredHeight, Fonts.RobotoFontFamily, (int)TextSizes.RegularText, false));

                currentYOffset_Left += requiredHeight;
            }

            x = columnWidth + (int)HorisontalSpacing.Large;
            var currentYOffset_Right = y;

            page.Elements.Add(new Label("Indicators", x, currentYOffset_Right, columnWidth * 4 / 5, 7, Fonts.RobotoBold, 7, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Label("Score", x + columnWidth * 4 / 5, currentYOffset_Right, columnWidth / 5, 7, Fonts.RobotoBold, 7, TextAlign.Right, RgbColor.Black));
            currentYOffset_Right += 13;
            page.Elements.Add(new Line(x, currentYOffset_Right, _report.PageMaxWidth, currentYOffset_Right, 0.5f, Colors.LineColor, LineStyle.Dots));
            currentYOffset_Right += 3;

            var indicators = pillar.Indicators.OrderBy(ind => ind.Number, _indicatorComparer);

            foreach (RiskRatingGovernanceIndicator indicator in indicators)
            {
                page.Elements.Add(new Label(indicator.Name, x, currentYOffset_Right, columnWidth * 4 / 5, 7, Fonts.RobotoRegular, 7, TextAlign.Left, RgbColor.Black));
                page.Elements.Add(new Label(indicator.Score.ToString(), x + columnWidth * 4 / 5, currentYOffset_Right, columnWidth / 5, 7, Fonts.RobotoRegular, 7, TextAlign.Right, RgbColor.Black));
                currentYOffset_Right += 10;
                page.Elements.Add(new Line(x, currentYOffset_Right, _report.PageMaxWidth, currentYOffset_Right, 0.5f, Colors.LineColor, LineStyle.Dots));
                currentYOffset_Right += 3;
            }

            currentYOffset_Left = Math.Max(currentYOffset_Left, currentYOffset_Right);
            currentYOffset_Left += (float)VerticalSpacing.Large;

            page.Elements.Add(new Line(0, currentYOffset_Left, _report.PageMaxWidth, currentYOffset_Left, 0.5f, Colors.LineColor, LineStyle.Dots));

            return currentYOffset_Left + (float)VerticalSpacing.Small;
        }

        private float AddIssueEsgRiskRating(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y + (float)VerticalSpacing.Small;
            float value1 = (float)issue.ManagementRisk.UnmanagedRisk.Value;

            page.Elements.Add(new Label("Rating Overview", x, currentYOffset, maxWidth, 10.5f + 2f, Fonts.RobotoBold, 10.5f, TextAlign.Left, RgbColor.Black));
            currentYOffset += (float)TextSizes.SubSectionTitle + (float)VerticalSpacing.Small;
            currentYOffset += 10f;

            page.Elements.Add(new RiskRating_CustomBulletChart
            {
                Top = currentYOffset,
                Left = x,
                Width = maxWidth,
                Value = value1,
                Assessment = issue.Cluster.Assessment.ToString(),
                RiskRatingClusterList = _dataSource.MaterialIssuesClusters,
                BarHeight = 15
            });
            currentYOffset += 60;

            
            var analystComment = "Sustainalytics assesses governance - related risks and opportunities by determining the extent to which a company’s governance practices detract from or add to the company’s ability to execute on its business strategy. Sustainalytics’ Corporate Governance Research evaluates the governance structures, practices, and behavior of a company and its ability to build sustainable, long-term value that can be delivered to shareholders and other stakeholders in a fair and transparent manner.";
   
                var style = new FormattedTextAreaStyle(Fonts.RobotoFontFamily, 7f, false)
                {
                    Paragraph = { Align = TextAlign.Left, Indent = 0, SpacingAfter = 0, AllowOrphanLines = false }
                };
            currentYOffset += 10f;
            var analystCommentTextArea = new FormattedTextArea(analystComment, x + 8f, currentYOffset + 5f, x + maxWidth - 20f, 150f, style);
            page.Elements.Add(new Line(x, currentYOffset + 35f, x + maxWidth, currentYOffset + 35f, analystCommentTextArea.GetRequiredHeight()+20f, new RgbColor(236, 241, 246)));
            page.Elements.Add(analystCommentTextArea);
            

            maxWidth = _report.PageMaxWidth / 2;

            var left = maxWidth;
            var top = y + (float)VerticalSpacing.Small;

            AddRiskRatingDistribution(issue, page, left, top, maxWidth);

            top += 140f;

            AddRelativePerformance(issue, page, left, top, maxWidth);

            currentYOffset += 180f;

            return currentYOffset;
        }

        private void AddRiskRatingDistribution(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float left, float top, float maxWidth)
        {
            left += (float)HorisontalSpacing.Large;
            maxWidth -= (float)HorisontalSpacing.Large;

            float currentYOffset = top;

            page.Elements.Add(new Label("ESG Risk Rating Distribution", left, currentYOffset, maxWidth, 11, Fonts.RobotoBold, 8.5f, TextAlign.Left, RgbColor.Black));
            currentYOffset += 5;

            RiskRating_CustomColumnChartGroup chartObj = new RiskRating_CustomColumnChartGroup();
            chartObj.Left = left;
            chartObj.Top = currentYOffset;
            chartObj.Width = maxWidth;
            chartObj.Height = 170;
            chartObj.RiskRatingClusterList = _dataSource.OverallClusters;
            chartObj.Assessment = issue.Cluster.Assessment.ToString();

            chartObj.UniverseChartValues = _dataSource.UniverseMEIAggregateDataPointsDictionary.ContainsKey(issue.ExternalId)
               ? _dataSource.UniverseMEIAggregateDataPointsDictionary[issue.ExternalId].Data
               : Enumerable.Empty<RiskRatingDataPoint>();
            chartObj.IndustryChartValues = _dataSource.IndustryMEIAggregateDataPointsDictionary.ContainsKey(issue.ExternalId)
               ? _dataSource.IndustryMEIAggregateDataPointsDictionary[issue.ExternalId].Data
               : Enumerable.Empty<RiskRatingDataPoint>();
            chartObj.SubIndustryChartValues = _dataSource.SubIndustryMEIAggregateDataPointsDictionary.ContainsKey(issue.ExternalId)
               ? _dataSource.SubIndustryMEIAggregateDataPointsDictionary[issue.ExternalId].Data
               : Enumerable.Empty<RiskRatingDataPoint>();

            page.Elements.Add(chartObj);
        }

        private void AddRelativePerformance(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float left, float top, float maxWidth)
        {
            left += (float)HorisontalSpacing.Large;
            maxWidth -= (float)HorisontalSpacing.Large;

            if (_dataSource.Benchmark.MaterialEsgIssueBenchmarks == null)
                return;

            var meiBenchmark = _dataSource.Benchmark
                .MaterialEsgIssueBenchmarks
                .Where(x => x.MeiExternalId == issue.ExternalId)
                .SingleOrDefault();

            if (meiBenchmark == null) return;


            page.Elements.Add(new Label("Relative Performance", left, top, maxWidth, 11f, Fonts.RobotoBold, 8.5f, TextAlign.Left, RgbColor.Black));
            top += 15;

            Table benchmarkTable = GetDefaultTable(left, top, maxWidth, 100);
            benchmarkTable.CellDefault.Border.Bottom.LineStyle = LineStyle.Dots;
            benchmarkTable.CellDefault.Border.Bottom.Width = 0.5f;
            benchmarkTable.CellDefault.Border.Color = RgbColor.Gray;
            benchmarkTable.CellDefault.VAlign = VAlign.Center;
            benchmarkTable.Columns.Add(maxWidth * 0.05f);
            benchmarkTable.Columns.Add(maxWidth * 0.45f);
            benchmarkTable.Columns.Add(maxWidth * 0.25f);
            benchmarkTable.Columns.Add(maxWidth * 0.25f);

            var row = benchmarkTable.Rows.Add(10);
            row.CellDefault.VAlign = VAlign.Center;
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add("Rank", Fonts.RobotoBold, 7f);
            row.Cells.Add("Percentile", Fonts.RobotoBold, 7f);
            row.CellDefault.Border.Bottom.LineStyle = LineStyle.None;

            row = benchmarkTable.Rows.Add(10);
            row.CellDefault.VAlign = VAlign.Top;
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(new FormattedTextArea($"<p>(1<sup><font size='0'>st</font></sup> = lowest risk)</p>",
                0f, 0f, 60, 9f, Fonts.RobotoFontFamily, 7f, false));
            row.Cells.Add(new FormattedTextArea($"<p>(1<sup><font size='0'>st</font></sup> = lowest risk)</p>",
                0f, 0f, 60, 9f, Fonts.RobotoFontFamily, 7f, false));

            int percentile = 0;


            row = benchmarkTable.Rows.Add(20f);

            row.Cells.Add(new Rectangle(0f, 0f, 10f, 10f, new RgbColor(204, 204, 204), new RgbColor(204, 204, 204)));
            row.Cells.Add(new Label("Global Universe", 5f, 0f, 100f, 7f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            if (meiBenchmark.UniversePerformanceRisk != null)
            {
                row.Cells.Add(new FormattedTextArea(string.Format("<b>{0}</b> out of {1}",
                    meiBenchmark.UniversePerformanceRisk.Rank.ToString(),
                    meiBenchmark.UniversePerformanceRisk.Count.ToString()),
                    0f, 0f, maxWidth * 0.25f, 9f, Fonts.RobotoFontFamily, 7f, false));

                if (int.TryParse(Math.Round(meiBenchmark.UniversePerformanceRisk.Percentile * 100, 0, MidpointRounding.AwayFromZero).ToString(), out percentile))
                    row.Cells.Add(ReportHelper.AddOrdinal(percentile), Fonts.RobotoBold, 7f);
                else
                    row.Cells.Add("N/A", Fonts.RobotoBold, 7f);
            }
            else
            {
                row.Cells.Add(new FormattedTextArea("<b>{N/A}</b> out of {N/A}", 0f, 0f, maxWidth * 0.25f, 9f, Fonts.RobotoFontFamily, 7f, false));

                row.Cells.Add("N/A", Fonts.RobotoBold, 7f);
            }

            row = benchmarkTable.Rows.Add(20f);
            row.Cells.Add(new Rectangle(0f, 0f, 10f, 10f, new RgbColor(142, 175, 200), new RgbColor(142, 175, 200)));
            var industryName = _dataSource.CompanyProfile.PeerGroup + " (Industry Group)";
            var industryNameLenght = Fonts.RobotoRegular.GetTextWidth(industryName, 7);
            if (industryNameLenght > 100)
            {
                row.Cells.Add(new TextArea(industryName, 5f, 1f, 100f, 20f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            else
            {
                row.Cells.Add(new Label(industryName, 5f, 0f, 100f, 9f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            row.Cells.Add(new FormattedTextArea(string.Format("<b>{0}</b> out of {1}",
                meiBenchmark.IndustryPerformanceRisk.Rank.ToString(),
                meiBenchmark.IndustryPerformanceRisk.Count.ToString()),
                0f, 0f, maxWidth * 0.25f, 9f, Fonts.RobotoFontFamily, 7f, false));

            if (int.TryParse(Math.Round(meiBenchmark.IndustryPerformanceRisk.Percentile * 100, 0, MidpointRounding.AwayFromZero).ToString(), out percentile))
                row.Cells.Add(ReportHelper.AddOrdinal(percentile), Fonts.RobotoBold, 7f);
            else
                row.Cells.Add("N/A", Fonts.RobotoBold, 7f);

            page.Elements.Add(benchmarkTable);


            row = benchmarkTable.Rows.Add(20f);

            row.Cells.Add(new Rectangle(0f, 0f, 10f, 10f, new RgbColor(29, 96, 143), new RgbColor(29, 96, 143)));
            var subIndustryName = _dataSource.CompanyProfile.SubPeerGroup + " (Subindustry)";
            var subIndustryNameLenght = Fonts.RobotoRegular.GetTextWidth(subIndustryName, 7);
            if (subIndustryNameLenght > 100)
            {
                row.Cells.Add(new TextArea(subIndustryName, 5f, 1f, 100f, 20f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            else
            {
                row.Cells.Add(new Label(subIndustryName, 5f, 0f, 100f, 9f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            row.Cells.Add(new FormattedTextArea(string.Format("<b>{0}</b> out of {1}",
                meiBenchmark.SubIndustryPerformanceRisk.Rank.ToString(),
                meiBenchmark.SubIndustryPerformanceRisk.Count.ToString()),
                0f, 0f, maxWidth * 0.25f, 9f, Fonts.RobotoFontFamily, 7f, false));

            if (int.TryParse(Math.Round(meiBenchmark.SubIndustryPerformanceRisk.Percentile * 100, 0, MidpointRounding.AwayFromZero).ToString(), out percentile))
                row.Cells.Add(ReportHelper.AddOrdinal(percentile), Fonts.RobotoBold, 7f);
            else
                row.Cells.Add("N/A", Fonts.RobotoBold, 7f);

            page.Elements.Add(benchmarkTable);
        }


        private float AddAnalystCommentary(PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y + (float)VerticalSpacing.Small;

            var analystViewComment = "Sustainalytics assesses governance-related risks and opportunities by determining the extent to which a company’s governance practices detract from or add to the company’s ability to execute on its business strategy. Sustainalytics’ Corporate Governance Research evaluates the governance structures, practices, and behavior of a company and its ability to build sustainable, long-term value that can be delivered to shareholders and other stakeholders in a fair and transparent manner.";

            if (!string.IsNullOrWhiteSpace(analystViewComment)) //issue.AnalystViewComment.Value
            {
                FormattedTextArea textArea = new FormattedTextArea(analystViewComment, x, currentYOffset, maxWidth, 500, Fonts.RobotoFontFamily, 7, false);

                currentYOffset += textArea.GetRequiredHeight() + 10;

                page.Elements.Add(textArea);
            }

            return currentYOffset;
        }

        private float AddPillarsTable(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth, float maxHeight)
        {
            
            float currentYOffset = y;
            Table indicatorsTable = PdfReportSectionGenerator.GetDefaultTable(x, currentYOffset, maxWidth, maxHeight);
            var indicatorNameCellWidth = maxWidth * 0.55f;

            indicatorsTable.Columns.Add(maxWidth * 0.55f);
            indicatorsTable.Columns.Add(maxWidth * 0.15f);
            indicatorsTable.Columns.Add(maxWidth * 0.15f);
            indicatorsTable.Columns.Add(maxWidth * 0.15f);

            // header row
            var row = indicatorsTable.Rows.Add(10);
            row.Cells.Add(new Label("Pillar", 0f, 0f, (float)(maxWidth * 0.15) - 5f, 20f, Fonts.RobotoRegular, 7f));
            row.Cells.Add(new Label("Score", 0f, 0f, (float)(maxWidth * 0.15) - 5f, 20f, Fonts.RobotoRegular, 7f));
            row.Cells.Add(new Label("Weight", 0f, 0f, (float)(maxWidth * 0.15), 20f, Fonts.RobotoRegular, 7f));
            row.Cells.Add(new Label("Weighted Score", 0f, 0f, (float)(maxWidth * 0.15), 20f, Fonts.RobotoRegular, 7f, TextAlign.Center));
            row.CellDefault.Border.Bottom.LineStyle = LineStyle.Solid;
            row.CellDefault.Border.Bottom.Width = 1f;
            row.CellDefault.Border.Color = RgbColor.Black;
            row.CellDefault.VAlign = VAlign.Center;

            currentYOffset += row.ActualRowHeight;


            var sortedList = issue.Indicators.Where(a => a.IndicatorType == IndicatorType.StandardIndicator).OrderBy(a => a.Code);
            foreach (var indicator in sortedList)
            {
                row = indicatorsTable.Rows.Add(15);
                row.Cells.Add(indicator.Name, Fonts.RobotoRegular, 7);
                row.Cells.Add(indicator.RawScore.Value.ToString("0.0"), Fonts.RobotoRegular, 7);
                row.Cells.Add(indicator.WeightInMei.Value.ToString("0.0%"), Fonts.RobotoRegular, 7);
                row.Cells.Add(new Label(indicator.WeightedScoreInMei.Value.ToString("0.0"), 0f, 0f, (float)(maxWidth * 0.15), 15f, Fonts.RobotoRegular, 7f, TextAlign.Center));
                row.CellDefault.Border.Bottom.LineStyle = LineStyle.Solid;
                row.CellDefault.Border.Bottom.Width = 0.5f;
                row.CellDefault.Border.Color = RgbColor.Gray;
                row.CellDefault.VAlign = VAlign.Center;

                PageElementPositions.Add(new PageElementPosition
                {
                    Name = issue.Name+"_"+indicator.Name,
                    PageNumber = page.PageNumber,
                    HorizontalPosition = x,
                    VerticalPosition = currentYOffset,
                    Width = indicatorNameCellWidth,
                    Height = row.ActualRowHeight,
                });
                currentYOffset += row.ActualRowHeight;
            }

            row = indicatorsTable.Rows.Add(30);
            row.Cells.Add(new Label("Totals", 0f, 0f, (float)(maxWidth * 0.15) - 5f, 20f, Fonts.RobotoBold, 7f));
            row.Cells.Add(new Label(String.Empty, 0f, 0f, (float)(maxWidth * 0.15) - 5f, 20f, Fonts.RobotoBold, 7f));
            row.Cells.Add(new Label("100.0%", 0f, 0f, (float)(maxWidth * 0.15), 20f, Fonts.RobotoBold, 7f));
            row.Cells.Add(new Label(issue.ManagementRisk.Management.Value.ToString("0.0"), 0f, 0f, (float)(maxWidth * 0.15), 20f, Fonts.RobotoBold, 7f, TextAlign.Center));
            row.CellDefault.VAlign = VAlign.Bottom;
            row.CellDefault.Border.Top.LineStyle = LineStyle.Solid;
            row.CellDefault.Border.Top.Width = 1f;
            row.CellDefault.Border.Color = RgbColor.Black;
            page.Elements.Add(indicatorsTable);

            currentYOffset += 10;

            return currentYOffset;
        }

        private float AddManagement(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y;

            page.Elements.Add(new Label("Management".ToUpperInvariant(), x, currentYOffset, maxWidth, (float)TextSizes.SubSectionTitle, Fonts.MontserratRegular, (float)TextSizes.SubSectionTitle, TextAlign.Left, RgbColor.Black));
            currentYOffset += 40;

            RiskRating_RangeBarChart chartObj = new RiskRating_RangeBarChart();
            chartObj.Left = x;
            chartObj.Top = currentYOffset;
            chartObj.Width = maxWidth+50f;
            chartObj.Value1 = issue.ManagementRisk.Exposure.Value;
            chartObj.Value2 = issue.ManagementRisk.ManageableRisk.Value;
            chartObj.Value3 = issue.ManagementRisk.ManagedRisk.Value;
            chartObj.Value4 = issue.ManagementRisk.Management.Value;
            chartObj.BarHeight = 10f;
            chartObj.ChartType = RangeChartType.MEI_Management;
            chartObj.CompanyName = _dataSource.CompanyProfile.CompanyName;
            page.Elements.Add(chartObj);
            currentYOffset += 50;

            double percent = Math.Round((chartObj.Value2 / chartObj.Value1) * 100, 0, MidpointRounding.AwayFromZero);
            var chartText = string.Format("{0}% of the total issue risk exposure is manageable. As such, the management score is applied to this {0}% of the issue risk exposure.", percent);

            page.Elements.Add(new Line(x, currentYOffset, x + maxWidth, currentYOffset, 0.5f, Colors.LineColor));
            currentYOffset += 10;

            page.Elements.Add(new Label(chartText,
                                x,
                                currentYOffset,
                                maxWidth,
                                50,
                                Fonts.RobotoRegular, 6, TextAlign.Left, RgbColor.Black));
            currentYOffset += 20;

            return currentYOffset;
        }

        private float AddRatingDetails(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y;

            page.Elements.Add(new Label("Rating Details".ToUpperInvariant(), x, currentYOffset, maxWidth, (float)TextSizes.SubSectionTitle, Fonts.MontserratRegular, (float)TextSizes.SubSectionTitle, TextAlign.Left, RgbColor.Black));
            currentYOffset += 20;

            RiskRating_RangeBarChart chartObj = new RiskRating_RangeBarChart();
            chartObj.Left = x;
            chartObj.Top = currentYOffset;
            chartObj.Width = maxWidth;
            chartObj.Value1 = (float)issue.ManagementRisk.Exposure.Value;
            chartObj.Value2 = (float)issue.ManagementRisk.ManagedRisk.Value;
            chartObj.Value3 = (float)issue.ManagementRisk.UnmanagedRisk.Value;
            chartObj.BarHeight = 10f;
            chartObj.ChartType = RangeChartType.MEI_RatingDetails;
            page.Elements.Add(chartObj);
            currentYOffset += 60;

            return currentYOffset;
        }

        float AddMeiRiskDetailsChart(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y + (float)VerticalSpacing.Small;
            var columnWidth = (maxWidth - (float)HorisontalSpacing.Large) / 3;

            RiskRating_RiskRangeBarChart chartObj = new RiskRating_RiskRangeBarChart();
            chartObj.Left = x;
            chartObj.Top = currentYOffset;
            chartObj.Width = columnWidth;
            chartObj.Value1 = issue.ManagementRisk.Exposure.Value;
            chartObj.Value2 = issue.ManagementRisk.ManageableRisk.Value;
            chartObj.Value3 = issue.ManagementRisk.ManagedRisk.Value;
            chartObj.Value4 = issue.ManagementRisk.ManagementGap.Value;
            chartObj.Value5 = issue.ManagementRisk.UnmanageableRisk.Value;
            chartObj.Value6 = issue.ManagementRisk.UnmanagedRisk.Value;
            chartObj.BarHeight = 10f;
            chartObj.ChartType = RiskRangeChartType.IssueRiskDetails;
            page.Elements.Add(chartObj);
            currentYOffset += currentYOffset;
            return currentYOffset;
        }

        float AddRiskBenchmark(RiskRatingMaterialEsgIssueBase issue, PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y + (float)VerticalSpacing.Small;
            var columnWidth = (maxWidth - (float)HorisontalSpacing.Large) / 2;

            page.Elements.Add(new Label($"Subindustry Overview1111 – {_dataSource.CompanyProfile.SubPeerGroup}", x, currentYOffset, maxWidth, 11, Fonts.MontserratRegular, 11, TextAlign.Left, RgbColor.Black));
            currentYOffset += 30;

            MaterialEsgIssuesBenchmark meiBenchmark = new MaterialEsgIssuesBenchmark();
            if (_dataSource.Benchmark.MaterialEsgIssueBenchmarks != null)
                meiBenchmark = _dataSource.Benchmark.MaterialEsgIssueBenchmarks.FirstOrDefault(a => a.MeiExternalId == issue.ExternalId);


            RiskRating_CustomColumnChartGroup chartObj = new RiskRating_CustomColumnChartGroup();
            chartObj.Left = x;
            chartObj.Top = currentYOffset + 15f;
            chartObj.Width = columnWidth;
            chartObj.Height = 210;
            chartObj.RiskRatingClusterList = _dataSource.OverallClusters;
            chartObj.IndustryChartValues = null;
            chartObj.SubIndustryChartValues =  _dataSource.SubIndustryMEIAggregateDataPointsDictionary.ContainsKey(issue.ExternalId)
                ? _dataSource.SubIndustryMEIAggregateDataPointsDictionary[issue.ExternalId].Data
                : Enumerable.Empty<RiskRatingDataPoint>();
            page.Elements.Add(chartObj);
            
            page.Elements.Add(new Label("Subindustry Exposure/Management", columnWidth + (float)HorisontalSpacing.Large, currentYOffset - 10, columnWidth, 8, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            currentYOffset += 15;

            var chart = new RiskRating_ScatterChart(columnWidth + (float)HorisontalSpacing.Large, currentYOffset, columnWidth - 30)
            {
                SubPeerGroupBenchmark = meiBenchmark.PeersList,
                ShowGridLines = true,
                ChartType = ScatterChartType.Baseline,
                CompanyId = _dataSource.CompanyId,
                SubIndustryDataPoints = _dataSource.SubIndustryMEIRiskRatingPerformanceDictionary[issue.ExternalId], //_dataSource.SubIndustryRiskRatingPerformanceList,
                GlobalUniverseDataPoints=_dataSource.GlobalUniverseRiskRatingPerformanceList,
                SubIndustry=_dataSource.CompanyProfile.SubPeerGroup,
                MarketCapMin = (float)meiBenchmark.MarketCapMin,
                MarketCapMax = (float)meiBenchmark.MarketCapMax,
                RiskRatingClusterList = _dataSource.OverallClusters,
            };

            page.Elements.Add(chart);
            currentYOffset += 185;

            return currentYOffset;
        }


    }
}